package com.ysy.logistics.service.sale.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysy.common.myenum.StatusEnum;
import com.ysy.common.resp.ResultData;
import com.ysy.logistics.entities.echarts.Series;
import com.ysy.logistics.entities.sale.CusOrder;
import com.ysy.logistics.entities.sale.CusOrderGoods;
import com.ysy.logistics.entities.sale.Customer;
import com.ysy.logistics.entities.sale.dto.CusOrderDto;
import com.ysy.logistics.entities.sale.dto.CusOrderGoodsDto;
import com.ysy.logistics.entities.stock.GoodsCapacity;
import com.ysy.logistics.entities.stock.InBoundList;
import com.ysy.logistics.entities.stock.StoreGoods;
import com.ysy.logistics.entities.stock.StoreHouse;
import com.ysy.logistics.entities.supplier.SupGoods;
import com.ysy.logistics.entities.supplier.SupOrder;
import com.ysy.logistics.mapper.sale.CusOrderGoodsMapper;
import com.ysy.logistics.mapper.sale.CusOrderMapper;
import com.ysy.logistics.mapper.sale.CustomerMapper;
import com.ysy.logistics.mapper.stock.GoodsCapacityMapper;
import com.ysy.logistics.mapper.stock.InBoundListMapper;
import com.ysy.logistics.mapper.stock.StoreGoodsMapper;
import com.ysy.logistics.mapper.stock.StoreHouseMapper;
import com.ysy.logistics.mapper.supplier.SupGoodsMapper;
import com.ysy.logistics.service.sale.CusOrderService;
import com.ysy.logistics.service.system.SysNoticeService;
import com.ysy.logistics.util.LinearRegression;
import com.ysy.logistics.util.PageInfo;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassDescription:
 * @Author:姚斯羽
 * @Create:2025/4/9 22:44
 **/
@Service
public class CusOrderServiceImpl extends ServiceImpl<CusOrderMapper, CusOrder> implements CusOrderService {

    @Resource
    private CusOrderMapper cusOrderMapper;
    @Resource
    private CustomerMapper customerMapper;
    @Resource
    private CusOrderGoodsMapper cusOrderGoodsMapper;
    @Resource
    private StoreGoodsMapper storeGoodsMapper;
    @Resource
    private SupGoodsMapper supGoodsMapper;
    @Resource
    private GoodsCapacityMapper goodsCapacityMapper;
    @Resource
    private StoreHouseMapper storeHouseMapper;
    @Resource
    private InBoundListMapper inBoundListMapper;
    @Resource
    private SysNoticeService sysNoticeService;
    @Override
    public Page<CusOrder> listByPage(PageInfo<CusOrder> pageInfo) {
        return cusOrderMapper.listByPage(pageInfo.getPage(), pageInfo.getCriteria());

    }

    @Override
    public ResultData saveSupOrderDto(CusOrderDto cusOrderDto) {
        CusOrder cusOrder = cusOrderDto.toCusOrder();
        boolean flag = StringUtils.isBlank(cusOrder.getCustomerId())
                || StringUtils.isBlank(cusOrder.getCreateUser())
                || Objects.isNull(cusOrder.getCreateTime());
        if (flag) {
            return ResultData.fail("订单信息不完整");
        }
        //查询客户
        Customer customer = customerMapper.selectById(cusOrder.getCustomerId());
        if (Objects.isNull(customer)) {
            return ResultData.fail("客户不存在");
        }
        if (StringUtils.equals(customer.getStatus(), StatusEnum.DISABLE.getCode())) {
            return ResultData.fail("客户状态为停用，不能下单");
        }
        //添加信息
        cusOrder.setCustomerName(customer.getName());
        if (Objects.isNull(cusOrder.getCreateTime())){
            cusOrder.setCreateTime(new Date());
        }
        //计算总价
        long totalPrice = cusOrderDto.getGoodsList().stream()
                .map(cusOrderGoods -> cusOrderGoods.getGoodsPrice() * cusOrderGoods.getGoodsNum())
                .mapToLong(Integer::longValue).sum();
        cusOrder.setTotalPrice((int) totalPrice);
        //生成订单编号
        String firstLetter = PinyinUtil.getFirstLetter(customer.getName(), "").toUpperCase() ;
        //获取当前年月日小时分秒
        String date = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        cusOrder.setOrderNum(firstLetter + date);
        cusOrder.setOrderStatus(0).setStorageStatus(0);
        //保存订单信息
        cusOrderMapper.insert(cusOrder);

        //商品添加订单ID
        cusOrderDto.getGoodsList().forEach(cusOrderGoods -> {
            cusOrderGoods.setId(null);
            cusOrderGoods.setOrderId(cusOrder.getId());
        });
        //保存商品信息
        cusOrderGoodsMapper.insert(cusOrderDto.getGoodsList());
        return ResultData.success("");
    }

    @Override
    public List<CusOrderGoodsDto> getGoodsListByOrderId(String id) {
        if (StringUtils.isBlank(id)){
            return null;
        }
        return cusOrderGoodsMapper.getGoodsListByOrderId(id);

    }

    @Override
    @Transactional
    public ResultData outBoutById(String id) {
        //先查询出订单
        CusOrder cusOrder = cusOrderMapper.selectById(id);
        if (Objects.isNull(cusOrder)){
            return ResultData.fail("订单不存在");
        }
        //判断订单状态
        if (cusOrder.getStorageStatus().equals("1")){
            return ResultData.fail("订单状态为已出库，不能重复出库");
        }
        //查询出订单商品信息
        LambdaQueryWrapper<CusOrderGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CusOrderGoods::getOrderId,id);
        List<CusOrderGoods> cusOrderGoods = cusOrderGoodsMapper.selectList(queryWrapper);
        //判断库存是否充足
        for (CusOrderGoods cusOrderGood : cusOrderGoods) {
            //查询商品库存
            LambdaQueryWrapper<StoreGoods> sGoodsQueryWrapper = new LambdaQueryWrapper<>();
            sGoodsQueryWrapper.eq(StoreGoods::getGoodsId,cusOrderGood.getGoodsId())
                    .eq(StoreGoods::getStoreHouseId,cusOrderGood.getStoreHouseId())
                    .eq(StoreGoods::getGoodsCapacityId,cusOrderGood.getGoodsCapacityId());
            StoreGoods one = storeGoodsMapper.selectOne(sGoodsQueryWrapper);
            if (Objects.isNull(one)||one.getStoreNum() < cusOrderGood.getGoodsNum()){
                //查询出商品名称
                SupGoods supGoods = supGoodsMapper.selectById(one.getGoodsId());
                //给相应用户发送通知
                //查询出库房信息
                StoreHouse storeHouse = storeHouseMapper.selectById(one.getStoreHouseId());
                String storeName = Optional.ofNullable(storeHouse).map(StoreHouse::getName).orElse("");
                String title ="仓库[" + storeName + "]商品库存不足";
                String content = String.format( "%s 所在仓库,%s 商品不足\n 请查看补充！",storeName, supGoods.getName() );
                sysNoticeService.saveNoticeStock(title,content);
                return ResultData.fail(supGoods.getName()+"->商品库存不足，出库失败！");
            }
        }
        //库存充足，修改订单状态和仓库库存
        HashMap<String, Integer> map = new HashMap<>();
        List<StoreGoods> updateStoreGoodsList = new ArrayList<>();
        for (CusOrderGoods cusOrderGood : cusOrderGoods) {
            //根据Id查询出已有库存
            LambdaQueryWrapper<StoreGoods> sGoodsQueryWrapper = new LambdaQueryWrapper<>();
            sGoodsQueryWrapper.eq(StoreGoods::getGoodsId,cusOrderGood.getGoodsId())
                    .eq(StoreGoods::getStoreHouseId,cusOrderGood.getStoreHouseId())
                    .eq(StoreGoods::getGoodsCapacityId,cusOrderGood.getGoodsCapacityId());
            StoreGoods one = storeGoodsMapper.selectOne(sGoodsQueryWrapper);
            if (Objects.nonNull(one)){
                //查询出规格
                GoodsCapacity byEntity = goodsCapacityMapper.selectById(one.getGoodsCapacityId());
                //修改库存
                StoreGoods storeGoods = new StoreGoods();
                storeGoods.setId(one.getId())
                        .setStoreNum(one.getStoreNum() - cusOrderGood.getGoodsNum());
                updateStoreGoodsList.add(storeGoods);
                //计算容量
                Integer capacity = byEntity.getCapacity() * cusOrderGood.getGoodsNum();
                //存储仓库修改信息
                if (map.containsKey(one.getStoreHouseId())){
                    map.put(one.getStoreHouseId(),map.get(one.getStoreHouseId()) + capacity);
                }else {
                    map.put(one.getStoreHouseId(),capacity);
                }
            }
        }
        //更新仓库
        List<StoreHouse> updateStoreHouseList = new ArrayList<>();
        //出库单
        List<InBoundList> outBoundList = new ArrayList<>();
        String outPerson = "系统出库";
        String outResponsible = cusOrder.getCustomerName();
        String orderNum = cusOrder.getOrderNum();
        //构建入库单编号
        String outBoundNo = PinyinUtil.getFirstLetter(cusOrder.getCustomerName(), "").toUpperCase()+DateUtil.format(new Date(), "yyyyMMddHHmmss");

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            //查询出仓库
            LambdaQueryWrapper<StoreHouse> sHouseQueryWrapper = new LambdaQueryWrapper<>();
            sHouseQueryWrapper.eq(StoreHouse::getId,entry.getKey());
            StoreHouse one = storeHouseMapper.selectOne(sHouseQueryWrapper);
            //修改仓库
            StoreHouse storeHouse = new StoreHouse();
            storeHouse.setId(one.getId())
                    .setUsedCapacity(one.getUsedCapacity() - entry.getValue());
            updateStoreHouseList.add(storeHouse);
            //添加出库单
            InBoundList inBoundList = new InBoundList();
            inBoundList.setId(null)
                    .setInBoundNo(outBoundNo)
                    .setInBoundType("1")
                    .setInBoundTypeId(id)
                    .setInBoundPerson(outPerson)
                    .setInBoundResponsible(outResponsible)
                    .setInBoundStatus("1")
                    .setWarehouseId(one.getId())
                    .setOrderNum(orderNum)
                    .setCreateTime(new Date());
            outBoundList.add(inBoundList);
        }
        //更新库存
        storeGoodsMapper.insertOrUpdate(updateStoreGoodsList);
        storeHouseMapper.insertOrUpdate(updateStoreHouseList);
        //修改订单状态
        LambdaUpdateWrapper<CusOrder> cusOrderLqw = new LambdaUpdateWrapper<>();
        cusOrderLqw.set(CusOrder::getStorageStatus,"1")
                .set(CusOrder::getStorageTime,new Date())
                .eq(CusOrder::getId,id);
        cusOrderMapper.update(cusOrderLqw);
        inBoundListMapper.insertOrUpdate(outBoundList);

        return ResultData.success();
    }

    @Override
    public void flushOrder() {
        //已发货未收货
        getOrderStatus("1","2");
        //未发货
        getOrderStatus("0","1");
        //未出库退货
        notOutStore();
        //已出库退货
        getOrderStatus("3","5");
    }

    private void notOutStore() {
        //退货中且未出库的订单直接修改为退货完成
        LambdaUpdateWrapper<CusOrder> cusOrderLqw = new LambdaUpdateWrapper<>();
        cusOrderLqw.set(CusOrder::getOrderStatus, "4")
                .eq(CusOrder::getOrderStatus, "3")
                .eq(CusOrder::getStorageStatus, "0");
        cusOrderMapper.update(cusOrderLqw);
    }
    private void outStore() {
        //查询出已出库且退货中的订单
        LambdaQueryWrapper<CusOrder> cusOrderLqw = new LambdaQueryWrapper<>();
        cusOrderLqw.eq(CusOrder::getOrderStatus, "3")
                .eq(CusOrder::getStorageStatus, "1");
        List<CusOrder> cusOrders = cusOrderMapper.selectList(cusOrderLqw);
        if (CollectionUtil.isNotEmpty(cusOrders)){

        }
    }

    @Override
    public ResultData backOrder(String id) {
        if (StringUtils.isBlank(id)){
            return ResultData.fail("订单ID不能为空");
        }
        //查询出订单信息
        CusOrder cusOrder = cusOrderMapper.selectById(id);
        if (Objects.isNull(cusOrder)){
            return ResultData.fail("订单不存在");
        }
        if (cusOrder.getOrderStatus().equals("3")|| cusOrder.getOrderStatus().equals("4")|| cusOrder.getOrderStatus().equals("5")){
            return ResultData.fail("该订单状态正在退货");
        }
        //修改状态为退回中
        LambdaUpdateWrapper<CusOrder> cusOrderLqw = new LambdaUpdateWrapper<>();
        cusOrderLqw.set(CusOrder::getOrderStatus, "3")
                .eq(CusOrder::getId, id);
        cusOrderMapper.update(cusOrder,cusOrderLqw);
        return ResultData.success();
    }

    @Override
    public Series getTotal(List<String> dateArray) {
        Series series = new Series();
        series.setName("销售单");
        List<Long> date = new ArrayList<>();
        //预测使用数据
        List<Double> x = new ArrayList<>();
        List<Double> y = new ArrayList<>();
        //预测坐标
        Double xNext = 2.0;
        if (!CollectionUtils.isEmpty(dateArray)){
            for (int i = 0; i < dateArray.size(); i++) {
                Long total =  cusOrderMapper.sumTotalPriceByDate(dateArray.get(i)+" 00:00:00",dateArray.get(i)+" 23:59:59");
                total = Objects.isNull(total)?0:total;
                date.add(total/100);
                x.add(i+1+0.0);
                y.add(total+0.0);
                xNext +=i;
            }
            //数据预测
            double[] train = LinearRegression.train(x, y);
            double predict = LinearRegression.predict(train, xNext);
            predict = predict<0?0:predict;
            date.add((long)predict/100);
        }
        series.setData(date);
        return series;
    }

    /***
     * 模拟更新
     */
    private void getOrderStatus(String nowStatus,String newStatus){
        if (StringUtils.isBlank(nowStatus)|| StringUtils.isBlank(newStatus)){
            return;
        }
        LambdaQueryWrapper<CusOrder> lqw = new LambdaQueryWrapper<>();
        lqw.select(CusOrder::getId).eq(CusOrder::getOrderStatus, nowStatus)
                .eq(CusOrder::getStorageStatus,"1");
        if (cusOrderMapper.exists(lqw)){
            List<CusOrder> cusOrders = cusOrderMapper.selectList(lqw);
            if (!CollectionUtils.isEmpty(cusOrders)){
                List<String> ids = cusOrders.stream().map(CusOrder::getId).collect(Collectors.toList());
                flushOrderStatus(ids,newStatus);
            }
        }
    }

    /**
     * 随机更新订单状态
     * @param ids
     * @param orderStatus
     */
    private void flushOrderStatus(List<String> ids,String orderStatus){
        if (CollectionUtils.isEmpty(ids)|| StringUtils.isBlank(orderStatus)){
            return;
        }
        //要更新订单状态的Id

        List<String> collect = ids.stream().filter(id -> generBoolean()).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(collect)){
            //不是发货的订单，不需要更新快递号
            if (!"1".equals(orderStatus)){
                LambdaUpdateWrapper<CusOrder> lqw = new LambdaUpdateWrapper<>();
                lqw.in(CusOrder::getId,collect).set(CusOrder::getOrderStatus,orderStatus);
                cusOrderMapper.update(null,lqw);
            }else {
                collect.forEach(id -> {
                    CusOrder cusOrder = new CusOrder();
                    cusOrder.setId(id);
                    cusOrder.setOrderStatus(1);
                    //物流单号
                    String code = generBoolean()?"SF":"YZ";
                    code+= DateUtil.format(new Date(),"yyyyMMddHHmmss");
                    cusOrder.setExpressId(code);
                    cusOrderMapper.updateById(cusOrder);
                });
            }
        }
    }

    public static boolean generBoolean() {
        return  Math.random() > 0.75;
    }

}
